package com.xxq.semester.controller.utils;
import com.xxq.semester.component.RateLimitComponent;
import com.xxq.semester.entity.utils.ResponseEntity;
import com.xxq.semester.entity.user.Users;
import com.xxq.semester.security.JwtTokenProvider;
import com.xxq.semester.service.user.IUsersService;
import com.xxq.semester.service.utils.RedisService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletRequest;
import java.beans.Transient;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/api/auth")
@Tag(name = "用户认证", description = "提供用户登录、注册、登出等认证相关功能")
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private IUsersService usersService;

    @Autowired
    private JwtTokenProvider tokenProvider;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RateLimitComponent rateLimitComponent;
    @Operation(summary = "用户登录", description = "用户通过用户名和密码进行登录")
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest, HttpServletRequest request) {
        try {
            String clientIp = rateLimitComponent.getClientIp(request);
            
            // 检查登录限流
            if (!rateLimitComponent.loginRateLimit(clientIp)) {
                return ResponseEntity.fail("登录尝试过于频繁，请稍后再试");
            }

            // 验证用户凭证
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginRequest.getUsername(),
                            loginRequest.getPassword()
                    )
            );

            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 获取用户信息
            Users user = usersService.getUserByUsername(loginRequest.getUsername());
            if (user == null) {
                return ResponseEntity.fail("用户不存在");
            }

            // 生成JWT Token
            String token = tokenProvider.generateToken(user.getId().longValue(), user.getUsername());

            // 将token存储到Redis中，设置过期时间为24小时
            redisService.setString(
                    "login:token:" + token,
                    user.getId().toString(),
                    24, TimeUnit.HOURS
            );

            // 存储用户会话信息
            redisService.setString(
                    "login:user:" + user.getId(),
                    token,
                    24, TimeUnit.HOURS
            );

            // 记录用户在线状态
            redisService.setString(
                    "online:user:" + user.getId(),
                    "1",
                    24, TimeUnit.HOURS
            );

            Map<String, Object> response = new HashMap<>();
            response.put("token", token);
            response.put("user", user);
            response.put("expiresIn", 24 * 60 * 60); // 24小时，单位秒

            return ResponseEntity.success(response);

        } catch (Exception e) {
            return ResponseEntity.fail("用户名或密码错误");
        }
    }
    @Operation(summary = "用户注册", description = "用户通过用户名、邮箱和密码进行注册")
    @Transactional
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest, HttpServletRequest request) {
        try {
            String clientIp = rateLimitComponent.getClientIp(request);
            
            // 检查注册限流
            if (!rateLimitComponent.registerRateLimit(clientIp)) {
                return ResponseEntity.fail("注册过于频繁，请稍后再试");
            }

            // 检查用户名是否已存在
            if (usersService.getUserByUsername(registerRequest.getUsername()) != null) {
                return ResponseEntity.fail("用户名已存在");
            }

            // 检查邮箱是否已存在
            if (usersService.getUserByEmail(registerRequest.getEmail()) != null) {
                return ResponseEntity.fail("邮箱已被注册");
            }

            // 创建新用户
            Users user = new Users();
            user.setUsername(registerRequest.getUsername());
            user.setEmail(registerRequest.getEmail());
            user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
            user.setCreatedAt(LocalDateTime.now());
            // 设置默认值
            user.setRole(registerRequest.role); // 默认为老师角色
            user.setLastUpdate(LocalDateTime.now());

            boolean success = usersService.save(user);

            if (success) {
                return ResponseEntity.success("注册成功");
            } else {
                return ResponseEntity.fail("注册失败");
            }

        } catch (Exception e) {
            // 添加详细的错误日志
            e.printStackTrace();
            return ResponseEntity.fail("注册过程中发生错误: " + e.getMessage());
        }
    }
    @Operation(summary = "用户登出", description = "用户通过JWT Token进行登出")
    @PostMapping("/logout")
    public ResponseEntity<?> logout(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                
                // 从Redis中删除token
                redisService.delete("login:token:" + token);
                
                // 获取用户ID并删除用户会话
                Long userId = tokenProvider.getUserIdFromToken(token);
                if (userId != null) {
                    redisService.delete("login:user:" + userId);
                    redisService.delete("online:user:" + userId);
                }
            }

            return ResponseEntity.success("登出成功");

        } catch (Exception e) {
            return ResponseEntity.fail("登出失败");
        }
    }
    @Operation(summary = "获取用户信息", description = "通过JWT Token获取当前登录用户的个人信息")
    @GetMapping("/profile")
    public ResponseEntity<?> getProfile(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                String username = tokenProvider.getUsernameFromToken(token);
                Users user = usersService.getUserByUsername(username);
                
                if (user != null) {
                    // 隐藏敏感信息
                    user.setPassword(null);
                    return ResponseEntity.success(user);
                }
            }

            return ResponseEntity.fail("获取用户信息失败");

        } catch (Exception e) {
            return ResponseEntity.fail("获取用户信息失败");
        }
    }
    @Operation(summary = "刷新Token", description = "通过旧的JWT Token刷新获取新的Token")
    @PostMapping("/refresh")
    public ResponseEntity<?> refreshToken(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String oldToken = authHeader.substring(7);
                
                if (tokenProvider.validateToken(oldToken)) {
                    String username = tokenProvider.getUsernameFromToken(oldToken);
                    Users user = usersService.getUserByUsername(username);
                    
                    if (user != null) {
                        // 生成新的token
                        String newToken = tokenProvider.generateToken(user.getId().longValue(), user.getUsername());
                        
                        // 删除旧token
                        redisService.delete("login:token:" + oldToken);
                        
                        // 存储新token
                        redisService.setString(
                                "login:token:" + newToken,
                                user.getId().toString(),
                                24, TimeUnit.HOURS
                        );
                        
                        redisService.setString(
                                "login:user:" + user.getId(),
                                newToken,
                                24, TimeUnit.HOURS
                        );
                        
                        Map<String, Object> response = new HashMap<>();
                        response.put("token", newToken);
                        response.put("expiresIn", 24 * 60 * 60);
                        
                        return ResponseEntity.success(response);
                    }
                }
            }

            return ResponseEntity.fail("刷新Token失败");

        } catch (Exception e) {
            return ResponseEntity.fail("刷新Token失败");
        }
    }
    @Operation(summary = "验证Token", description = "通过JWT Token验证用户登录状态")
    @GetMapping("/validate")
    public ResponseEntity<?> validateToken(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                
                if (tokenProvider.validateToken(token) && redisService.hasKey("login:token:" + token)) {
                    return ResponseEntity.success("Token有效");
                }
            }

            return ResponseEntity.fail("Token无效");

        } catch (Exception e) {
            return ResponseEntity.fail("Token验证失败");
        }
    }
    // 内部类：登录请求
    @Setter
    @Getter
    public static class LoginRequest {
        private String username;
        private String password;

    }

    // 内部类：注册请求
    @Setter
    @Getter
    public static class RegisterRequest {
        private String username;
        private String email;
        private String password;
        private String role;

    }
}
